package com.starlink.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.convert.Convert;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageHelper;
import com.starlink.client.ras.RasClient;
import com.starlink.client.ras.request.ActivationSingleCodeActivationRequest;
import com.starlink.client.ras.request.GoodsListEvidenceRequest;
import com.starlink.client.ras.response.ActivationSingleCodeActivationResponse;
import com.starlink.client.ras.response.GoodsListEvidenceResponse;
import com.starlink.client.ras.response.RasBaseResponse;
import com.starlink.common.enums.ErrorCode;
import com.starlink.common.exception.BusinessException;
import com.starlink.mapper.*;
import com.starlink.model.domain.MallBooksSpecificationDO;
import com.starlink.model.domain.SchoolbagBooksStorageDO;
import com.starlink.model.domain.SchoolbagGroupBagDO;
import com.starlink.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Pageable;
import com.starlink.common.utils.AssertUtil;
import com.starlink.model.dtomapper.MallBooksRasDtoMapper;
import com.starlink.model.domain.MallBooksRasDO;
import com.starlink.model.request.MallBooksRasRequest;
import com.starlink.model.util.MallBooksRasConvert;
import com.starlink.model.vo.MallBooksRasVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.starlink.common.enums.MallBooksRasEnum.NOT_SELL;
import static com.starlink.common.enums.MallBooksRasEnum.SELL;
import static com.starlink.utils.IDUtils.getId;
import static com.starlink.utils.PageUtils.getOrderBy;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zhanghong
 */
@Service
public class MallBooksRasServiceImpl extends ServiceImpl<MallBooksRasMapper, MallBooksRasDO> implements MallBooksRasService {
    @Autowired
    private MallBooksRasMapper mallBooksRasMapper;
    @Autowired
    private RasClient rasClient;
    @Autowired
    private MallBooksSpecificationService specificationService;
    @Autowired
    private MallBooksOrderDetailsMapper booksOrderDetailsMapper;
    @Autowired
    private ShoppingCartOrderDetailsMapper cartOrderDetailsMapper;
    @Autowired
    private MallIntegrationOrderDetailsMapper integrationOrderDetailsMapper;
    @Autowired
    private SchoolbagBooksStorageService schoolbagBooksStorageService;
    @Autowired
    private SchoolbagGroupBagService schoolbagGroupBagService;

    @Override
    public MallBooksRasVO getByKey(long id) {
        MallBooksRasVO mallBooksRasVO = MallBooksRasDtoMapper.INSTANCE.do2VO(getById(id));
        return mallBooksRasVO;
    }

    @Override
    public PageInfo<MallBooksRasVO> pageQuery(Pageable pageable,MallBooksRasRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<MallBooksRasVO> list = mallBooksRasMapper.pageQuery(request);
        return new PageInfo(list);
    }

    @Override
    public List<MallBooksRasVO> listQuery(MallBooksRasRequest request) {
        List<MallBooksRasDO> list = mallBooksRasMapper.selectDOList(MallBooksRasDtoMapper.INSTANCE.request2DO(request));
        List<MallBooksRasVO> mallBooksRasVOS = MallBooksRasConvert.buildMallBooksRasVoList(list);
        return mallBooksRasVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(MallBooksRasRequest request) {
        Long mallBooksId = request.getMallBooksId();
        Map<String, String> rasMap = request.getRasMap();
        Long rasGoodsId = request.getRasGoodsId();
        Long specificationId = request.getSpecificationId();
        AssertUtil.assertNotNull(mallBooksId,"书籍ID不能为空!");
        AssertUtil.assertNotNull(rasMap,"RAS数据不能为空!");
        AssertUtil.assertNotNull(rasGoodsId,"RAS商品ID不能为空!");
        AssertUtil.assertNotNull(specificationId,"商品规格ID不能为空!");
        List<String> rasCodes = new ArrayList<>();
        List<String> rasUrls = new ArrayList<>();
        rasMap.forEach((key,value)->{
            AssertUtil.assertNotNull(key,"RAS_CODE不能为空!");
            AssertUtil.assertNotNull(value,"RAS_URL不能为空!");
            rasCodes.add(key);
            rasUrls.add(value);
        });
        // 校验RAS编码是否重复（书籍）
        List<MallBooksRasDO> booksRasDO = this.lambdaQuery()
                .in(MallBooksRasDO::getRasCode, rasCodes)
                .list();
        if (CollectionUtils.isNotEmpty(booksRasDO)) {
            List<String> codes = booksRasDO.stream().map(MallBooksRasDO::getRasCode).collect(Collectors.toList());
            StringBuilder stringBuilder = new StringBuilder();
            codes.forEach(code -> {
                stringBuilder.append(code + ",");
            });
            throw new BusinessException(ErrorCode.PARAM_ERROR, "该书籍RAS编码" + stringBuilder + "已存在!");
        }
        // 校验RAS编码是否重复（书包书籍）
        Boolean storageExists = schoolbagBooksStorageService.lambdaQuery().in(SchoolbagBooksStorageDO::getRasCode, rasCodes).exists();
        AssertUtil.assertFalse(storageExists, "该RAS编码已存在");

        // 校验RAS编码是否重复（书包）
        Boolean bagExists = schoolbagGroupBagService.lambdaQuery().in(SchoolbagGroupBagDO::getBagCode, rasCodes).exists();
        AssertUtil.assertFalse(bagExists, "该RAS编码已存在");

        List<MallBooksRasDO> mallBooksRasDOList = new ArrayList<>();
        for (int i = 0; i < rasCodes.size();i++){
            MallBooksRasRequest rasRequest = new MallBooksRasRequest();
            rasRequest.setRasCode(rasCodes.get(i));
            rasRequest.setRasUrl(rasUrls.get(i));
            rasRequest.setIsSell(NOT_SELL.getType());
            rasRequest.setMallBooksId(mallBooksId);
            rasRequest.setRasGoodsId(rasGoodsId);
            rasRequest.setSpecificationId(specificationId);
            rasRequest.setId(getId());
            MallBooksRasDO mallBooksRasDO = MallBooksRasDtoMapper.INSTANCE.request2DO(rasRequest);
            mallBooksRasDOList.add(mallBooksRasDO);
        }
        mallBooksRasMapper.batchInsertDO(mallBooksRasDOList);
        ActivationSingleCodeActivationRequest activationRequest = new ActivationSingleCodeActivationRequest();
        activationRequest.setAbLabel(rasUrls);
        activationRequest.setGoodsId(rasGoodsId.intValue());
        activationRequest.setWrapSpecs("1份/本");
        activationRequest.setActivationType("单码激活");
        RasBaseResponse<ActivationSingleCodeActivationResponse> rasBaseResponse = rasClient.activationSingleCodeActivation(activationRequest);
        Integer labelNum = rasBaseResponse.getData().getLabelNum();
        if (labelNum==rasCodes.size()){
            //库存+1
            Map<String, Long> map = new HashMap<>();
            map.put("specificationId",specificationId);
            map.put("quantity",Long.valueOf(labelNum));
            specificationService.addQuantity(map);
            return true;
        }else {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "RAS激活失败!");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(MallBooksRasRequest request) {
        AssertUtil.assertNotNull(request.getId(), "id不能为空");
        saveOrUpdate(MallBooksRasDtoMapper.INSTANCE.request2DO(request));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDOByIds(String ids,Long specificationId) {
        AssertUtil.assertNotNull(ids,"ID不能为空!");
        AssertUtil.assertNotNull(specificationId,"规格ID不能为空!");
        String[] idArry = Convert.toStrArray(ids);
        List<Long> list = Arrays.stream(idArry).map(Long::valueOf).collect(Collectors.toList());
        List<MallBooksRasDO> rasDOS = this.lambdaQuery()
                .in(MallBooksRasDO::getId, list)
                .list();
        boolean anyMatch = rasDOS.stream().anyMatch(item -> SELL.getType().equals(item.getIsSell()));
        if (anyMatch){
            throw new BusinessException("当前芯片所绑定书籍已售出不能删除!");
        }
        MallBooksSpecificationDO specificationDO = specificationService.lambdaQuery()
                .eq(MallBooksSpecificationDO::getId, specificationId)
                .last("FOR UPDATE")
                .one();
        Long inventory = specificationDO.getInventory();
        if (inventory>0L){
            //查询已卖出的待发货的书籍数量
            long sum = 0L;
            List<Long> inventorys = booksOrderDetailsMapper.selectInventoryBySpecificationId(specificationId);
            List<Long> carInventorys = cartOrderDetailsMapper.selectInventoryBySpecificationId(specificationId);
            List<Long> integrationInventorys = integrationOrderDetailsMapper.selectInventoryBySpecificationId(specificationId);
            if (inventorys==null){
                inventorys = new ArrayList<>();
            }
            if (carInventorys==null){
                carInventorys = new ArrayList<>();
            }
            if (integrationInventorys==null){
                integrationInventorys = new ArrayList<>();
            }
            carInventorys.addAll(integrationInventorys);
            sum = Stream.concat(inventorys.stream(), carInventorys.stream())
                    // 将 Stream<Long> 转换为 LongStream，然后求和
                    .mapToLong(Long::longValue)
                    .sum();
            List<MallBooksRasDO> booksRasDOS = this.lambdaQuery().eq(MallBooksRasDO::getIsSell, 0).eq(MallBooksRasDO::getSpecificationId,specificationId).list();
            int size = booksRasDOS.size();
            if (size>sum){
                mallBooksRasMapper.deleteDOByIds(idArry);
                Map<String, Long> map = new HashMap<>();
                map.put("specificationId",specificationId);
                map.put("quantity",1L);
                specificationService.subQuantity(map);
            }else {
                throw new BusinessException(ErrorCode.PARAM_ERROR, "当前编码书籍已全部售出或积分商品关联部分库存,不能再删除编码!");
            }
        }
        return true;
    }

    @Override
    public Boolean check(MallBooksRasRequest request) {
        Long rasGoodsId = request.getRasGoodsId();
        AssertUtil.assertNotNull(rasGoodsId,"RAS商品ID不能为空!");
        GoodsListEvidenceRequest evidenceRequest = new GoodsListEvidenceRequest();
        evidenceRequest.setId(rasGoodsId.intValue());
        GoodsListEvidenceRequest listEvidenceRequest = new GoodsListEvidenceRequest();
        listEvidenceRequest.setId(rasGoodsId.intValue());
        RasBaseResponse<GoodsListEvidenceResponse> response = rasClient.goodsListEvidence(listEvidenceRequest);
        List<GoodsListEvidenceResponse.RasGoodsListPageDTO.RecordsDTO> records = response.getData().getRasGoodsListPage().getRecords();
        AssertUtil.assertNotEmpty(records,"RAS审核还未通过!");
        return true;
    }
}
